#include"src/global.h"
#include"src/word.h"
#include"src/syntax.h"
#include"src/semantic.h"
#include"src/common.h"
#include<string>
#include<vector>
#include<stdio.h>
#include<stdlib.h>

using std::string;
using std::vector;
using std::list;

//词法分析变量
vector<WordUnit>::iterator sym;
//符号表变量
Type *checkingType = new Type();	//保存正在被检查的变量类型
Type *currArray = new Type(); 	//ָ指向当前正在语义分析的数组
bool hasIdError = false;

//递归下降分析函数 
void program(){
	compoundstmt();
}

void compoundstmt(){		//每到Block语句需衍生子符号表
	Table *newTable = new Table();
	newTable->parent = topTable;
	if(topTable) topTable->addChild(newTable);
	topTable = newTable;
	if(*sym==LSB) sym++; 
	else error(LSB);
	stmts();
	if(*sym==RSB) sym++;
	else error(RSB);
	if(topTable->parent) topTable = topTable->parent;
}

void stmts(){
	if(*sym!=IF&&*sym!=WHILE&&*sym!=LSB&&*sym!=ID){
		return;
	}
	currSyntax->clear();
	stmt();
	stmts();
}

void stmt(){
	if(*sym==ID){
		currType->clear();
		currType->typeCode = INT;
		topTable->add(sym->value, *currType);
		currSyntax->clear();
		string id = sym->value;
		loc();
		if(*sym==SET) sym++;
		else error(SET);
		currSyntax = currSyntax->derive();
		boolexpr();
		emit(opASSIGN, currSyntax->place, new Operand(), currSyntax->parent->place);
		currSyntax = currSyntax->parent;
		if(*sym==SC) sym++;
		else error(SC);
	}

	else if(*sym==IF){
		sym++;
		if(*sym==LP) sym++;
		else error(LP);
		boolexpr();
		int quadNum1 = nextQuad(); 
		emit(opJZ, currSyntax->place, new Operand(), new Operand(-1, true));
		if(*sym==RP) sym++;
		else error(RP);
		if(*sym==THEN) sym++;
		else error(THEN);
		stmt();
		int quadNum2 = nextQuad();
		emit(opJMP, new Operand(), new Operand(), new Operand(-1, true));
		int quadNum3 = nextQuad();
		if(*sym==ELSE) sym++;
		else error(ELSE);
		stmt();
		backpatch(quadNum2, nextQuad());
		backpatch(quadNum1, quadNum3);
	}
	else if(*sym==WHILE){
		sym++;
		if(*sym==LP) sym++;
		else error(LP);
		int quadNum1 = nextQuad(); 
		boolexpr();
		int quadNum2 = nextQuad(); 
		emit(opJZ, currSyntax->place, new Operand(), new Operand(-1, true));
		if(*sym==RP) sym++;
		else error(RP);
		currBreakQuad = currBreakQuad->derive();		//While֮之后才衍生
		stmt();
		emit(opJMP, new Operand(), new Operand(), new Operand(quadNum1, true));		//每次循环布尔值需重算
		backpatch(quadNum2, nextQuad());
		if(currBreakQuad->breaklist.size()){		//break语句只往当前所在的while语句块跳转
			backpatch(currBreakQuad->breaklist, nextQuad()); 
			currBreakQuad->breaklist.clear();
		}
		currBreakQuad = currBreakQuad->parent;
	}
	else compoundstmt();
}

void loc(){
	string id;
	checkingType->elem = NULL;
	if(*sym==ID){
		id = sym->value;
		currSyntax->place = new Operand(topTable->getElem(id));
		sym++;
	}
	else error(ID);
	currSyntax = currSyntax->derive();
	currArray = topTable->getArrAddress(id);
	currSyntax->s = currSyntax->i;
	if(!topTable->isLegal(id, checkingType)){
		hasIdError = true;
		exit(0);		//程序强制结束
	}
	currSyntax->parent->place = currSyntax->s;
	currSyntax = currSyntax->parent;
}

void boolexpr(){
	arithexpr();
	currSyntax = currSyntax->derive(); 
	boolop();
	currSyntax->parent->place = currSyntax->s;
	currSyntax = currSyntax->parent;
}

void boolop(){
	if(*sym!=LT&&*sym!=LE&&*sym!=GT&&*sym!=GE&&*sym!=EQ){
		currSyntax->s = currSyntax->i;
		return;
	}
	Operand *new_operand = newTemp(checkingType->typeCode);
	if(*sym==LT){
		sym++;
		arithexpr();
		emit(opJL, currSyntax->i, currSyntax->place, new Operand(nextQuad()+3, true));
	}
	else if(*sym==LE){
		sym++;
		arithexpr();
		emit(opJLE, currSyntax->i, currSyntax->place, new Operand(nextQuad()+3, true));
	}
	else if(*sym==GT){
		sym++;
		arithexpr();
		emit(opJG, currSyntax->i, currSyntax->place, new Operand(nextQuad()+3, true));
	}
	else if(*sym==GE){
		sym++;
		arithexpr();
		emit(opJGE, currSyntax->i, currSyntax->place, new Operand(nextQuad()+3, true));
	}
	else if(*sym==EQ){
		sym++;
		arithexpr();
		emit(opJE, currSyntax->i, currSyntax->place, new Operand(nextQuad()+3, true));
	}
	emit(opASSIGN, new Operand(0), new Operand(), new_operand);
	emit(opJMP, new Operand(), new Operand(), new Operand(nextQuad()+2, true));
	emit(opASSIGN, new Operand(1), new Operand(), new_operand);
	currSyntax->s = new_operand;
}

void arithexpr(){
	multexpr();
	currSyntax = currSyntax->derive();
	arithexprprime();
	currSyntax->parent->place = currSyntax->s;
	currSyntax = currSyntax->parent;	
}

void arithexprprime(){
	if(*sym!=ADD&&*sym!=SUB){
		currSyntax->s = currSyntax->i;
		return;
	}
	if(*sym==ADD){
		sym++;
		multexpr();
		Operand *new_operand = newTemp(checkingType->typeCode); 
		emit(opADD, currSyntax->i, currSyntax->place, new_operand);
		currSyntax = currSyntax->derive();
		currSyntax->i = new_operand;
		arithexprprime();
		currSyntax->parent->s = currSyntax->s;
		currSyntax = currSyntax->parent;
	}
	else if(*sym==SUB){
		sym++;
		multexpr();
		Operand *new_operand = newTemp(checkingType->typeCode); 
		emit(opSUB, currSyntax->i, currSyntax->place, new_operand);
		currSyntax = currSyntax->derive();
		currSyntax->i = new_operand;
		arithexprprime();
		currSyntax->parent->s = currSyntax->s;
		currSyntax = currSyntax->parent;
	}
}

void multexpr(){
	simpleexpr();
	currSyntax = currSyntax->derive();
	multexprprime();
	currSyntax->parent->place = currSyntax->s;
	currSyntax = currSyntax->parent;
}

void multexprprime(){
	if(*sym!=MUL&&*sym!=DIV){
		currSyntax->s = currSyntax->i;
		return;
	}
	if(*sym==MUL){
		sym++;
		simpleexpr();
		Operand *new_operand = newTemp(checkingType->typeCode); 
		emit(opMUL, currSyntax->i, currSyntax->place, new_operand);
		currSyntax = currSyntax->derive();
		currSyntax->i = new_operand;
		multexprprime();
		currSyntax->parent->s = currSyntax->s;
		currSyntax = currSyntax->parent;
	}
	else if(*sym==DIV){
		sym++;
		simpleexpr();
		Operand *new_operand = newTemp(checkingType->typeCode); 
		emit(opDIV, currSyntax->i, currSyntax->place, new_operand);
		currSyntax = currSyntax->derive();
		currSyntax->i = new_operand;
		multexprprime();
		currSyntax->parent->s = currSyntax->s;
		currSyntax = currSyntax->parent;
	}
}

void simpleexpr(){
	if(*sym==LP){
		if(*sym==LP) sym++;	//这样写更结构化，上面的简写了
		else error(LP);
		currSyntax = currSyntax->derive();
		boolexpr();
		currSyntax->parent->place = currSyntax->place;
		currSyntax = currSyntax->parent;
		if(*sym==RP) sym++; 
		else error(RP);
	}
	else if(*sym==ID){
		currSyntax = currSyntax->derive();	//可以不用衍生
		loc(); 
		currSyntax->parent->place = currSyntax->place;
		currSyntax = currSyntax->parent;
	}
	else if(*sym==NUM){
		if(*sym==NUM){
			currSyntax->place = new Operand(atoi(sym->value.c_str()));
			sym++;
		}
		else error(NUM);
	}
}

//语法错误处理
void error(int expect){
	sym++;
	fprintf(stderr, "[-]SYNTAX ERROR: Expected %d\n", expect);
	exit(0); 		//强制退出，以免处理不合文法的代码时程序出错，健壮性还不行
}
